import asyncio
from MyTT import EMA
import numpy as np
import pandas as pd
from tqsdk import TqApi
from db_manager import connect_db, get_monitored_products
import time 
class AsyncOpenCloseStrategy:
    """异步开平仓策略"""
    def __init__(self, api: TqApi, symbols, lots=1):
        self.api = api
        self.symbols = symbols
        self.lots = lots
        self.running = False
        self.main_task = None
        self.active_symbols = set()  # 新增运行状态跟踪
        self.loop = asyncio.get_event_loop()


    # async def start(self):
    #     """启动策略（协程版本）"""
    #     print("************************已启动策略************************")
    #     self.running = True
    #     if self.main_task:
    #         self.main_task.cancel()
    #     # 使用当前循环创建任务
    #     #self.main_task = self.loop.create_task(self._run_all_symbols())
    #     self.main_task=await self._run_all_symbols()
    #     #self.main_task=self.looprun_until_complete(self._run_all_symbols())
    #     self.main_task=self.loop.run_until_complete(_run_all_symbols())  # 运行主协程[4,5](@ref)
    #     loop.close()
    #     return self.main_task

    def start(self):
        """启动策略（协程版本）"""
        print("************************已启动策略************************")
        self.running = True
        if self.main_task:
            self.main_task.cancel()
        # 使用当前循环创建任务
        #self.loop = asyncio.get_event_loop()
        self.main_task=self.loop.run_until_complete(self._run_all_symbols())  # 运行主协程[4,5](@ref)
        loop.close()
        return self.main_task

    async def _run_all_symbols(self):
        """并行处理所有品种"""
        print(f"开始处理品种列表: {self.symbols}")
        # 使用当前循环创建任务
        tasks = [asyncio.create_task(self._process_product(symbol)) for symbol in self.symbols]
        await asyncio.gather(*tasks)

    async def _process_product(self, symbol):
        """单个品种处理协程"""
        self.active_symbols.add(symbol)
        print(f"开始处理品种: {symbol}")
        try:
            klines = self.api.get_kline_serial(symbol, 300, 500)
            while self.running:
                print(f"{symbol} 正在运行...")  # 添加flush确保及时输出
                #deadline = time.time() + 0.5
                #await self.api.wait_update(deadline=deadline)  # 等待0.5秒  
                await asyncio.sleep(1)  # 指定循环
                async with self.api.register_update_notify() as update_chan:
                    async for _ in update_chan:
                        if self.api.is_changing(klines.iloc[-1], "datetime"):
                            if not klines.close.iloc[-1]:
                                print("K线已变化")
                                q = (3*klines.close + klines.low + klines.open + klines.high) / 6
                                ma_values = self._calculate_ma(q)
                                short_ma = ma_values['ma']
                                ema_7 = ma_values['ema']
                                
                                position = self.api.get_position(symbol)
                                
                                # 平空仓逻辑
                                if short_ma[-2] > ema_7[-2]:  
                                    if position.pos_short > 0:
                                        self.api.insert_order(symbol, direction="BUY", offset="CLOSE", 
                                                        volume=position.pos_short)
                                # 开多仓逻辑
                                if position.pos_long == 0 and position.pos_short == 0 and short_ma[-3] < ema_7[-3] and short_ma[-2] > ema_7[-2]:
                                    self.api.insert_order(symbol, direction="BUY", offset="OPEN", 
                                                    volume=self.lots)
                                    
                                # 平多仓逻辑
                                if short_ma[-2] < ema_7[-2]:  
                                    if position.pos_long > 0:
                                        self.api.insert_order(symbol, direction="SELL", offset="CLOSE", 
                                                        volume=position.pos_long)
                                # 开空仓逻辑
                                if position.pos_long == 0 and position.pos_short == 0 and short_ma[-3] > ema_7[-3] and short_ma[-2] < ema_7[-2]:
                                    self.api.insert_order(symbol, direction="SELL", offset="OPEN", 
                                                    volume=self.lots)
                        
        finally:
            self.active_symbols.remove(symbol)

    def _calculate_ma(self, q):
        """自定义权重计算（与原版完全一致）"""
        weights = np.arange(26, 0, -1)
        ma = []
        q_array = np.array(q)
        for i in range(len(q_array)):
            if i < 26:
                ma.append(np.nan)
                continue
            window = q_array[i-26:i+1]
            ma.append(np.dot(window, weights) / 351)
        
        ema_7 = EMA(pd.Series(ma), 7)
        return {'ma': ma, 'ema': ema_7.tolist()}

    async def stop(self):
        """停止策略"""
        self.running = False
        if self.main_task:
            await self.main_task
            self.main_task = None